package org.trade.order.service.impl;

import java.math.BigDecimal;
import java.util.Date;

import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.client.producer.SendResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.trade.common.api.ICouponApi;
import org.trade.common.api.IGoodsApi;
import org.trade.common.api.IUserApi;
import org.trade.common.constant.MQEnums;
import org.trade.common.constant.TradeEnums;
import org.trade.common.exception.AceMQException;
import org.trade.common.exception.AceOrderException;
import org.trade.common.protocol.coupon.ChangeCoponStatusReq;
import org.trade.common.protocol.coupon.ChangeCoponStatusRes;
import org.trade.common.protocol.coupon.QueryCouponReq;
import org.trade.common.protocol.coupon.QueryCouponRes;
import org.trade.common.protocol.goods.QueryGoodsReq;
import org.trade.common.protocol.goods.QueryGoodsRes;
import org.trade.common.protocol.goods.ReduceGoodsNumberReq;
import org.trade.common.protocol.goods.ReduceGoodsNumberRes;
import org.trade.common.protocol.mq.CancelOrderMQ;
import org.trade.common.protocol.order.ChangeOrderStatusReq;
import org.trade.common.protocol.order.ChangeOrderStatusRes;
import org.trade.common.protocol.order.ConfirmOrderReq;
import org.trade.common.protocol.order.ConfirmOrderRes;
import org.trade.common.protocol.user.ChangeUserMoneyReq;
import org.trade.common.protocol.user.ChangeUserMoneyRes;
import org.trade.common.protocol.user.QueryUserReq;
import org.trade.common.protocol.user.QueryUserRes;
import org.trade.common.rocketmq.AceMQProducer;
import org.trade.common.util.IDGenerator;
import org.trade.entity.TradeOrder;
import org.trade.mapper.TradeOrderMapper;
import org.trade.order.service.IOrderService;

import com.alibaba.fastjson.JSON;

@Service
public class OrderServiceImpl implements IOrderService {
	@Autowired
	private IGoodsApi goodsApi;
	@Autowired
	private TradeOrderMapper tradeOrderMapper;
	@Autowired
	private ICouponApi couponApi;
	@Autowired
	private IUserApi userApi;
	@Autowired
	private AceMQProducer aceMQProducer;

	@Transactional
	public ConfirmOrderRes confirmOrder(ConfirmOrderReq confirmOrderReq) {

		ConfirmOrderRes confimOrderRes = new ConfirmOrderRes();
		try {
			// 1.检查校验
			QueryGoodsReq queryGoodsReq = new QueryGoodsReq();
			queryGoodsReq.setGoodsId(confirmOrderReq.getGoodsId());
			QueryGoodsRes queryGoodsRes = goodsApi.queryGoods(queryGoodsReq);
			checkConfimOrderReq(confirmOrderReq, queryGoodsRes);

			// 2.创建不可见订单
			String orderId = saveNoConfimOrder(confirmOrderReq);
			// 3.调用远程服务，扣优惠券，和库存，如果调用成功--》更改订单状态可见，失败-=》发送mq消息，退订取消订单
			callRemoteService(confirmOrderReq, orderId);
			confimOrderRes.setOrderId(orderId);
		} catch (Exception e) {
			confimOrderRes.setRetCode(TradeEnums.RetEnum.FAIL.getCode());
			confimOrderRes.setRetInfo(e.getMessage());
		}

		return confimOrderRes;
	}

	private void callRemoteService(ConfirmOrderReq confimOrderReq, String orderId) {
		try {
			// 调用优惠券
			if (StringUtils.isNotBlank(confimOrderReq.getCouponId())) {
				ChangeCoponStatusReq changeCoponStatusReq = new ChangeCoponStatusReq();
				changeCoponStatusReq.setCouponId(confimOrderReq.getCouponId());
				changeCoponStatusReq.setIsUsed(TradeEnums.YesNoEnum.YES.getCode());
				changeCoponStatusReq.setOrderId(orderId);
				ChangeCoponStatusRes changeCoponStatusRes = couponApi.changeCoponStatus(changeCoponStatusReq);
				if (!changeCoponStatusRes.getRetCode().equals(TradeEnums.RetEnum.SUCCESS.getCode())) {
					throw new Exception("优惠券使用失败");
				}
			}
			// 扣余额
			if (confimOrderReq.getMoneyPaid() != null
					&& confimOrderReq.getMoneyPaid().compareTo(BigDecimal.ZERO) == 1) {
				ChangeUserMoneyReq changeUserMoneyReq = new ChangeUserMoneyReq();
				changeUserMoneyReq.setOrderId(orderId);
				changeUserMoneyReq.setUserId(confimOrderReq.getUserId());
				changeUserMoneyReq.setUserMoney(confimOrderReq.getMoneyPaid());
				changeUserMoneyReq.setMoneyLogType(TradeEnums.UserMoneyLogTypeEnum.PAID.getCode());
				ChangeUserMoneyRes changeUserMoneyRes = userApi.changeUserMoney(changeUserMoneyReq);
				if (!changeUserMoneyRes.getRetCode().equals(TradeEnums.RetEnum.SUCCESS.getCode())) {
					throw new Exception("扣用户余额失败");
				}
			}

			// 扣库存
			ReduceGoodsNumberReq reduceGoodsNumberReq = new ReduceGoodsNumberReq();
			reduceGoodsNumberReq.setOrderId(orderId);
			reduceGoodsNumberReq.setGoodsId(confimOrderReq.getGoodsId());
			reduceGoodsNumberReq.setGoodsNumber(confimOrderReq.getGoodsNumber());
			ReduceGoodsNumberRes reduceGoodsNumberRes = goodsApi.reduceGoodsNumber(reduceGoodsNumberReq);
			if (!reduceGoodsNumberRes.getRetCode().equals(TradeEnums.RetEnum.SUCCESS.getCode())) {
				throw new Exception("扣库存失败");
			}
			// 更改订单状态
			TradeOrder tradeOrder = new TradeOrder();
			tradeOrder.setOrderId(orderId);
			tradeOrder.setOrderStatus(TradeEnums.OrderStatusEnum.CONFIRM.getStatusCode());
			tradeOrder.setConfirmTime(new Date());
			int row = tradeOrderMapper.updateByPrimaryKeySelective(tradeOrder);
			if (row <= 0) {
				throw new Exception("扣库存失败");
			}
			throw new RuntimeException("xxxx");
		} catch (Exception ex) {
			// 发送mq消息
			CancelOrderMQ cancelOrderMQ = new CancelOrderMQ();
			cancelOrderMQ.setOrderId(orderId);
			cancelOrderMQ.setCouponId(confimOrderReq.getCouponId());
			cancelOrderMQ.setGoodsId(confimOrderReq.getGoodsId());
			cancelOrderMQ.setGoodsNumber(confimOrderReq.getGoodsNumber());
			cancelOrderMQ.setUserId(confimOrderReq.getUserId());
			cancelOrderMQ.setUserMoney(confimOrderReq.getMoneyPaid());
			try {
				SendResult sendResult = aceMQProducer.sendMessage(MQEnums.TopicEnum.ORDER_CANCEL, orderId,
						JSON.toJSONString(cancelOrderMQ));
			} catch (AceMQException e) {

			}
			throw new RuntimeException(ex.getMessage());
		}

	}

	private String saveNoConfimOrder(ConfirmOrderReq confimOrderReq) throws Exception {
		TradeOrder tradeOrder = new TradeOrder();
		tradeOrder.setOrderId(IDGenerator.generatorUUID());
		tradeOrder.setUserId(confimOrderReq.getUserId());
		tradeOrder.setOrderStatus(TradeEnums.OrderStatusEnum.NO_CONFIRM.getStatusCode());
		tradeOrder.setPayStatus(TradeEnums.PayStatusEnum.NO_PAY.getStatusCode());
		tradeOrder.setShippingStatus(TradeEnums.ShippingStatusEnum.NO_SHIP.getStatusCode());
		tradeOrder.setAddress(confimOrderReq.getAddress());
		tradeOrder.setConsignee(confimOrderReq.getConsignee());
		tradeOrder.setGoodsId(confimOrderReq.getGoodsId());
		tradeOrder.setGoodsNumber(confimOrderReq.getGoodsNumber());
		tradeOrder.setGoodsPrice(confimOrderReq.getGoodsPrice());
		BigDecimal goodsAmount = confimOrderReq.getGoodsPrice()
				.multiply(new BigDecimal(confimOrderReq.getGoodsNumber()));
		tradeOrder.setGoodsAmount(goodsAmount);
		BigDecimal shippingFee = calculateShippingFee(goodsAmount);
		if (confimOrderReq.getShippingFee().compareTo(shippingFee) != 0) {
			throw new Exception("快递费用不正确");
		}
		tradeOrder.setShippingFee(shippingFee);
		BigDecimal orderAmount = goodsAmount.add(shippingFee);
		if (orderAmount.compareTo(confimOrderReq.getOrderAmount()) != 0) {
			throw new Exception("订单总价异常，请重新下单!");
		}
		tradeOrder.setOrderAmount(orderAmount);// 订单总价
		String couponId = confimOrderReq.getCouponId();
		if (couponId != null) {
			QueryCouponReq queryCouponReq = new QueryCouponReq();
			queryCouponReq.setCouponId(couponId);
			QueryCouponRes queryCouponRes = couponApi.queryCoupon(queryCouponReq);
			if (queryCouponRes == null || !queryCouponRes.getRetCode().equals(TradeEnums.RetEnum.SUCCESS.getCode())) {
				throw new Exception("优惠券非法");
			}
			if (queryCouponRes.getIsUsed().equals(TradeEnums.YesNoEnum.NO.getCode())) {
				throw new Exception("优惠券已使用");
			}
			tradeOrder.setCouponId(couponId);
			tradeOrder.setCouponPaid(queryCouponRes.getCouponPrice());
		} else {
			tradeOrder.setCouponPaid(BigDecimal.ZERO);
		}
		if (confimOrderReq.getMoneyPaid() != null) {// 余额
			int r = confimOrderReq.getMoneyPaid().compareTo(BigDecimal.ZERO);
			if (r == -1) {
				throw new Exception("余额金额非法");
			}
			if (r == 1) {
				QueryUserReq queryUserReq = new QueryUserReq();
				queryUserReq.setUserId(confimOrderReq.getUserId());
				QueryUserRes queryUserRes = userApi.queryUser(queryUserReq);
				// 请求所传余额和数据库的余额做对比
				if (queryUserRes == null || !queryUserRes.getRetCode().equals(TradeEnums.RetEnum.SUCCESS.getCode())) {
					throw new Exception("用户非法");
				}
				if (queryUserRes.getUserMoney().compareTo(confimOrderReq.getMoneyPaid()) == -1) {
					throw new Exception("余额不足");
				}
				tradeOrder.setMoneyPaid(confimOrderReq.getMoneyPaid());
			}
		} else {
			tradeOrder.setMoneyPaid(BigDecimal.ZERO);
		}
		BigDecimal payAmount = orderAmount.subtract(tradeOrder.getMoneyPaid().subtract(tradeOrder.getCouponPaid()));
		tradeOrder.setPayAmount(payAmount);
		tradeOrder.setAddTime(new Date());
		int ret = this.tradeOrderMapper.insert(tradeOrder);
		if (ret != 1) {
			throw new Exception("保存订单失败");
		}
		return tradeOrder.getOrderId();
	}

	private BigDecimal calculateShippingFee(BigDecimal goodsAmount) {
		if (goodsAmount.doubleValue() > 100.00) {
			return BigDecimal.ZERO;
		} else {
			return new BigDecimal(10);
		}
	}

	private void checkConfimOrderReq(ConfirmOrderReq confimOrderReq, QueryGoodsRes queryGoodsRes) {
		if (confimOrderReq == null) {
			throw new AceOrderException("下单信息不能为空");
		}
		if (confimOrderReq.getUserId() == null) {
			throw new AceOrderException("会员账号不能为空");
		}
		if (confimOrderReq.getGoodsId() == null) {
			throw new AceOrderException("商品编号不能为空");
		}
		if (confimOrderReq.getGoodsNumber() == null || confimOrderReq.getGoodsNumber() <= 0) {
			throw new AceOrderException("购买数量不能小于0");
		}
		if (confimOrderReq.getAddress() == null) {
			throw new AceOrderException("商品地址不能为空");
		}
		if (queryGoodsRes == null || queryGoodsRes.getRetCode().equals(TradeEnums.RetEnum.SUCCESS)) {
			throw new AceOrderException("未查询到该商品[" + confimOrderReq.getGoodsId() + "]");
		}
		if (queryGoodsRes.getGoodsNumber() < confimOrderReq.getGoodsNumber()) {
			throw new AceOrderException("商品库存不足");
		}
		if (queryGoodsRes.getGoodsPrice().compareTo(confimOrderReq.getGoodsPrice()) != 0) {
			throw new AceOrderException("当前商品价格有变化,请重新下单");
		}
		if (confimOrderReq.getShippingFee() == null) {
			confimOrderReq.setShippingFee(BigDecimal.ZERO);
		}
		if (confimOrderReq.getOrderAmount() == null) {
			confimOrderReq.setOrderAmount(BigDecimal.ZERO);
		}
	}

	@Transactional
	public ChangeOrderStatusRes changeOrderStatus(ChangeOrderStatusReq changeOrderStatusReq) {
		TradeOrder record = new TradeOrder();
		record.setOrderId(changeOrderStatusReq.getOrderId());
		record.setOrderStatus(changeOrderStatusReq.getOrderStatus());
		ChangeOrderStatusRes changeOrderStatusRes = new ChangeOrderStatusRes();
		try {
			int num = tradeOrderMapper.updateByPrimaryKey(record);
			if (num <= 0) {
				throw new Exception("订单状态修改异常");
			}
			changeOrderStatusRes.setRetCode(TradeEnums.RetEnum.SUCCESS.getCode());
			changeOrderStatusRes.setRetInfo(TradeEnums.RetEnum.SUCCESS.getDesc());

		} catch (Exception e) {
			changeOrderStatusRes.setRetCode(TradeEnums.RetEnum.FAIL.getCode());
			changeOrderStatusRes.setRetInfo(e.getMessage());
		}
		return changeOrderStatusRes;
	}

}
